package com.example.mybatislearn.common.mapper.util;

import com.example.mybatislearn.common.lang.Pair;
import com.example.mybatislearn.common.mapper.converter.customer.SmartTypeConverter;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class ResolveTypeUtils {
    public static Pair<Class, Class> resolveTypeConverterKey(Class<?> typeConvereterType) {
        try {
            Type typeConverterInterface = getInterface(typeConvereterType);
            Type[] srcDestTypeArray = ((ParameterizedType) typeConverterInterface).getActualTypeArguments();


            return new Pair<>(getClass(srcDestTypeArray[0]), getClass(srcDestTypeArray[1]));
        } catch (Exception e) {
            throw new IllegalStateException("typeConvereterType is invalid:" + e.getMessage(), e);
        }
    }

    private static Class getClass(Type type) {
        if (type instanceof Class) {
            return (Class) type;
        }
        return (Class) ((ParameterizedType) type).getRawType();
    }

    private static Type getInterface(Class<?> typeConvereterType) {
        if (typeConvereterType == null || Object.class.equals(typeConvereterType)) {
            // 到头了
            return null;
        }

        Type typeConverterInterface = getTypeConverterInterface(typeConvereterType);
        if (typeConverterInterface == null) {
            return getInterface(typeConvereterType.getSuperclass());
        }

        return typeConverterInterface;
    }

    private static Type getTypeConverterInterface(Class<?> typeConvereterType) {
        Type[] interfaces = typeConvereterType.getGenericInterfaces();
        if (interfaces == null) {
            return null;
        }

        for (Type each : interfaces) {
            if (each != null && each instanceof ParameterizedType && SmartTypeConverter.class.equals(((ParameterizedType) each).getRawType())) {
                return each;
            }
        }
        return null;
    }
}
